package cn.uncode.rpc.spring;


import java.util.Arrays;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;

import cn.uncode.rpc.config.BasicCallerConfig;
import cn.uncode.rpc.config.CallerConfig;
import cn.uncode.rpc.config.ProtocolConfig;
import cn.uncode.rpc.config.RegistryConfig;
import cn.uncode.rpc.util.CollectionUtil;
import cn.uncode.rpc.util.FrameworkUtil;


public class CallerConfigBean<T> extends CallerConfig<T> implements FactoryBean<T>, BeanFactoryAware, InitializingBean, DisposableBean, BeanNameAware {

    private static final long serialVersionUID = 8381310907161365567L;

    private transient BeanFactory beanFactory;
    
	@Override
	public void setBeanName(String name) {
		this.setId(name);
	}

    @Override
    public T getObject() throws Exception {
        return getRef();
    }

    @Override
    public Class<?> getObjectType() {
        return getInterface();
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public void destroy() {
        super.destroy();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // basicConfig需要首先配置，因为其他可能会依赖于basicConfig的配置

        checkAndConfigBasicConfig();
        checkAndConfigProtocols();
        checkAndConfigRegistry();

    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

	/**
	 * 检查并配置basicConfig
	 */
	private void checkAndConfigBasicConfig() {
		if (getBasicCaller() == null) {
			if (UncodeNamespaceHandler.basicCallerConfigDefineNames.size() == 0) {
				if (beanFactory instanceof ListableBeanFactory) {
					ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
					String[] basicRefererConfigNames = listableBeanFactory.getBeanNamesForType(BasicCallerConfig.class);
					UncodeNamespaceHandler.basicCallerConfigDefineNames.addAll(Arrays.asList(basicRefererConfigNames));
				}
			}
			for (String name : UncodeNamespaceHandler.basicCallerConfigDefineNames) {
				BasicCallerConfig biConfig = beanFactory.getBean(name, BasicCallerConfig.class);
				if (biConfig == null) {
					continue;
				}
				if (UncodeNamespaceHandler.basicCallerConfigDefineNames.size() == 1) {
					setBasicReferer(biConfig);
				} else if (biConfig.isDefault() != null && biConfig.isDefault().booleanValue()) {
					setBasicReferer(biConfig);
				}
			}
		}
	}

	/**
	 * 检查是否已经装配protocols，否则按basicConfig--->default路径查找
	 */
	private void checkAndConfigProtocols() {
		if (CollectionUtil.isEmpty(getProtocols()) && getBasicCaller() != null
				&& !CollectionUtil.isEmpty(getBasicCaller().getProtocols())) {
			setProtocols(getBasicCaller().getProtocols());
		}
		if (CollectionUtil.isEmpty(getProtocols())) {
			for (String name : UncodeNamespaceHandler.protocolDefineNames) {
				ProtocolConfig pc = beanFactory.getBean(name, ProtocolConfig.class);
				if (pc == null) {
					continue;
				}
				if (UncodeNamespaceHandler.protocolDefineNames.size() == 1) {
					setProtocol(pc);
				} else if (pc.isDefault() != null && pc.isDefault().booleanValue()) {
					setProtocol(pc);
				}
			}
		}
		if (CollectionUtil.isEmpty(getProtocols())) {
			setProtocol(FrameworkUtil.getDefaultProtocolConfig());
		}
	}

	/**
	 * 检查并配置registry
	 */
	public void checkAndConfigRegistry() {
		if (CollectionUtil.isEmpty(getRegistries()) && getBasicCaller() != null
				&& !CollectionUtil.isEmpty(getBasicCaller().getRegistries())) {
			setRegistries(getBasicCaller().getRegistries());
		}
		if (CollectionUtil.isEmpty(getRegistries())) {
			for (String name : UncodeNamespaceHandler.registryDefineNames) {
				RegistryConfig rc = beanFactory.getBean(name, RegistryConfig.class);
				if (rc == null) {
					continue;
				}
				if (UncodeNamespaceHandler.registryDefineNames.size() == 1) {
					setRegistry(rc);
				} else if (rc.isDefault() != null && rc.isDefault().booleanValue()) {
					setRegistry(rc);
				}
			}
		}
		if (CollectionUtil.isEmpty(getRegistries())) {
			setRegistry(FrameworkUtil.getDefaultRegistryConfig());
		}
	}

    public void checkAndConfigExtInfo() {

    }


}
